home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: MegaDisc / MegaDisc 24 (1991-10)(MegaDisc Digital Publishing)(AU)(Disk 2 of 2).zip / MegaDisc 24 (1991-10)(MegaDisc Digital Publishing)(AU)(Disk 2 of 2).adf / ART_GALLERY / nick.c < prev    next >
C/C++ Source or Header  |  1991-09-26  |  31KB  |  978 lines

  1. /* Fractal NICK - by Dave Lyneham, 1991. */
  2.  
  3. /* Compile me with:
  4.  
  5.                            lc -Lm -cusf nick.c
  6.          
  7. */
  8.  
  9. /* If you are interested in any part of this program, how it works etc,
  10.    please contact me:
  11.    
  12.         (002) 23 4449
  13.         
  14.         49 Fitzroy Crescent,
  15.         DYNNYRNE,
  16.         TAS 7004.
  17. */
  18.  
  19. /* This program makes use of transformation matrices and bit planes to
  20.    plot the affine transformations needed to spell out the word NICK as a 
  21.    fractal.
  22.    
  23.    The process takes a couple of hours to run its course (on an A500 with no
  24.    special hardware) */
  25.    
  26. /* The way it works is well written about in the book 'Fractals Everywhere'.
  27.    The method I am using is called the detirministic approach to fractal
  28.    generation, in which a grid or bit plane is progressively manipulated
  29.    by a series of well chosen 'affine' transformations until the designed
  30.    shape appears.
  31.    
  32.    An affine transformation is any LINEAR action that can be done to a 
  33.    two dimensional surface to change it.
  34.    A rotation is an affine transformation; as is a scaling: making it
  35.    bigger or smaller. A translation (ie: moving it about in an X or Y
  36.    direction) is also affine. A 'shear', an action that skews a square into
  37.    a kite shape is another of these transformations.
  38.    
  39.    The affine transformations I have chosen below I have done so very
  40.    carefully. You will note that there are 13 of them. Now consider the
  41.    word NICK: 
  42.    
  43.    
  44.                    0          2   333   56666668   10     11
  45.                    01         2         5      8   10    11
  46.                    0 1        2    4    5      8   10   11
  47.                    0  1       2    4    5          10  11
  48.                    0   1      2    4    5          10 11
  49.                    0    1     2    4    5          1011
  50.                    0     1    2    4    5          1012
  51.                    0      1   2    4    5          10 12
  52.                    0       1  2    4    5          10  12
  53.                    0        1 2    4    5      9   10   12
  54.                    0         12    4    5      9   10    12
  55.                    0          2    4    57777779   10     12
  56.    
  57.             
  58.     The way it is drawn there are 13 different shapes that make up the word.
  59.     The 13 transformations correspond to the 13 shapes of the word NICK.
  60.     
  61.     The secret to chosing the right affine transformations is to consider the
  62.     final shape that will result from the process of drawing the word- in
  63.     this case the result will be roughly a rectangle of these dimensions:
  64.     
  65.     
  66.                    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  67.                    X                                       X
  68.                    X                                       X
  69.                    X                                       X
  70.                    X                                       X
  71.                    X                                       X
  72.                    X                                       X
  73.                    X                                       X
  74.                    X                                       X
  75.                    X                                       X
  76.                    X                                       X
  77.                    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  78.      
  79.      
  80.      Now, consider what needs to be done to this shape to turn it from being
  81.      a large rectangle into the first shape making up the word. It will be
  82.      something like this:-
  83.           
  84.           1) rotate it 90 degrees (anti-clockwise is positive)
  85.           2) translate it right a little (the width of the rectangle)
  86.           3) shrink it (scale it) so that it is only as high as the 
  87.              original rectangle's width.
  88.      
  89.      The other transformations can similarly be detirmined.
  90.       
  91.      Once this is done, the process begins where each transformation is
  92.      allowed to transform an original shape. (NOTE: It could be ANY shape
  93.      except the 'homogeneous' one (ie: empty, blank shape).
  94.      In my case the original shae is just a rectangle.
  95.      The transformations process this shape and produce a new shape.
  96.      This new shape is fed back into the transformations again and again
  97.      until the final fractal emerges. 
  98.      
  99.      This technique can be applied to more shapes than the word NICK.
  100.      Fractal ferns, trees mountain ranges can also be made by the same
  101.      process. Simply imagine the rough shape of the final image- fern, leaf
  102.      or what not, and then construct it with linear tranformations of
  103.      itself. Incidently, this process is described in a technical way by
  104.      the "Collage Theorem"- laid out in the book "Fractals Eveywhere".
  105.      
  106.      Another source of information I used was "Computer Graphics" 
  107.      by Hearn & Baker which described in great detail the use of matrices
  108.      in transforming points in space- in 3 dimensions as well as two.
  109.      
  110. */
  111.    
  112.    
  113. #include <stdlib.h>
  114. #include <math.h>
  115. #include <stdio.h>
  116. #include <exec/types.h>
  117. #include <libraries/dos.h>
  118. #include <intuition/intuition.h>
  119. #include <proto/all.h>
  120.  
  121. #define LIB_REV   33
  122. #define XOFF   0
  123. #define YOFF   100
  124.  
  125. #define WHITE   1
  126. #define BLACK   0
  127.  
  128. #define _HIRES_WIDTH    640
  129. #define _HIRES_HEIGHT   512
  130. #define _LORES_WIDTH    320
  131. #define _LORES_HEIGHT   256
  132. #define BORDERTHICK     10
  133.  
  134. #define BOOL            unsigned char
  135.  
  136. #define UBYTE           unsigned char
  137. #define USHORT          unsigned short int
  138. #define MATRIXTYPE      float
  139.  
  140. #define XONE         (MATRIXTYPE)(1)
  141. #define xmul(x, y)   ((x) * (y))
  142. #define xcos(x)      (cos((double)x))
  143.  
  144. #define rtod(x)      ((x) * 57.296)  /* rads to degrees */
  145. #define dtor(x)      ((x) * 0.01745) /* degrees to rads */
  146. #define xsin(x)      (sin((double)x))
  147. #define xtof(x)      (double)(x)
  148.  
  149. #define NO_TRANSFORMS      13
  150.  
  151. #define PLANE_COLS      (640)
  152. #define PLANE_ROWS      ((unsigned int)((double)(PLANE_COLS) * ((double)55 / (double)174)))
  153.  
  154.  
  155. #define MAX(x, y)   ((x > y) ? (x) : (y))
  156. #define MIN(x, y)   ((x < y) ? (x) : (y))
  157.  
  158. /* prototypes */
  159.  
  160. VOID kill_mtx(struct matrix *);
  161. VOID kill_bit_plane(struct bit_plane *);
  162. BOOL init_mtx(struct matrix *, unsigned int, unsigned int);
  163. BOOL init_bit_plane(struct bit_plane *, unsigned int, unsigned int);
  164. BOOL copy_bit_plane(struct bit_plane *, struct bit_plane *);
  165. BOOL copy_mtx(struct matrix *, struct matrix *);
  166. BOOL clr_bit_plane(struct bit_plane *);
  167. BOOL within_mtx(struct matrix *, unsigned int, unsigned int);
  168. BOOL within_bit_plane(struct bit_plane *, unsigned int, unsigned int);
  169. BOOL assn_mtx(struct matrix *, unsigned int, unsigned int, MATRIXTYPE);
  170. BOOL assn_bit_plane(struct bit_plane *, unsigned int, unsigned int, BOOL);
  171. BOOL valu_bit_plane(struct bit_plane *, unsigned int, unsigned int);
  172. MATRIXTYPE valu_mtx(struct matrix *, unsigned int, unsigned int);
  173. VOID prin_bit_plane(struct bit_plane *);
  174. VOID fill_mtx(struct matrix *, MATRIXTYPE []);
  175. VOID prin_bit_plane(struct bit_plane *);
  176. VOID prin_mtx(struct matrix *);
  177. VOID load_plane_matrix(struct RastPort *, struct bit_plane *);
  178. struct matrix *mul_mtx(struct matrix *, struct matrix *);
  179. struct matrix *id_mtx(unsigned int);
  180. struct matrix *shear_mtx(double, double);
  181. struct matrix *scale_mtx(double, double);
  182. struct matrix *rot_mtx(double);
  183. struct matrix *xlate_mtx(double, double);
  184.  
  185. VOID clr_screen(VOID);
  186. VOID OpenAll(VOID);
  187. VOID plot(struct Window *, USHORT, USHORT, USHORT);
  188. VOID openViewing(VOID);
  189. VOID closeViewing(VOID);
  190. VOID clean_exit(int);
  191. VOID setColours(VOID);
  192. VOID setColours(VOID);
  193.  
  194. VOID main(VOID);
  195.  
  196. struct matrix {
  197.        MATRIXTYPE *table;
  198.        unsigned int rows, cols;
  199. };
  200. /* Most calculations for the affine transformations are done with
  201.    this 'matrix' type, since this makes linear transformations relatively
  202.    easy to perform */ 
  203.  
  204. struct bit_plane {
  205.        UBYTE *table;
  206.        unsigned int rows, cols;
  207. };
  208. /* A 'bit-plane' is a "flash" name for a two dimensional array of BOOLEAN
  209.    values- stored as bits so as to make them as memory efficient as possible.
  210.    Whereas with matrices operations may include addition, subtraction etc,
  211.    bit-planes can be subject to logical ANDs, ORs etc. */ 
  212.  
  213. #define NULL_MATRIX    { NULL, 0, 0 } /* NULL matrix definition for 
  214.                                           global matrices */
  215.  
  216. /* globals */
  217.  
  218. /* The following matrices are used internally to return matrix values from
  219.    specific functions. At the end of the program, they are killed off by
  220.    the routine 'cleanExit' so as to give back all memory allocated by
  221.    AmigaDOS  */
  222. struct matrix prod_1 = NULL_MATRIX;
  223. struct matrix prod_2 = NULL_MATRIX; /* used by mul_mtx */
  224. struct matrix id     = NULL_MATRIX; /* identity matrix */
  225. struct matrix scl    = NULL_MATRIX; /* a scaling matrix */
  226. struct matrix shr    = NULL_MATRIX; /* a shearing matrix */
  227. struct matrix xlt    = NULL_MATRIX; /* a translation matrix */
  228. struct matrix rot    = NULL_MATRIX; /* a rotation matrix */
  229.    
  230. struct IntuitionBase   *IntuitionBase = NULL;
  231. struct GfxBase         *GfxBase = NULL;
  232. struct Window          *window = NULL;
  233. struct Screen          *screen = NULL;
  234. struct RastPort        *rp = NULL;
  235. struct ViewPort        *vp = NULL;
  236. struct IntuiMessage    *msg;
  237.  
  238. struct bit_plane s, t;
  239. struct matrix aff_mtx[NO_TRANSFORMS];
  240. struct matrix u, *v;
  241.  
  242.  
  243. VOID main(VOID)
  244. {
  245.  
  246.     int x, y;
  247.     unsigned int i, j;
  248.     unsigned int h, k;
  249.   
  250.     
  251.     /* The two grids that the fractals is drawn into */
  252.     init_bit_plane(&s, PLANE_ROWS, PLANE_COLS);
  253.     init_bit_plane(&t, PLANE_ROWS, PLANE_COLS);
  254.  
  255.     /* reserve space for the affine transformations */
  256.     for (i = 0; i < NO_TRANSFORMS; i++)
  257.         init_mtx(&aff_mtx[i], 3, 3);
  258.  
  259.     /* Must have a 1 in position [1,3] of the point vector when doing 
  260.        any sort of linear transformation. (Might as well do it here once
  261.        than millions of times in the loop below) */
  262.     init_mtx(&u, 1, 3);
  263.     assn_mtx(&u, 1, 3, XONE);
  264.     
  265.     
  266.     /* the matrices below are the three transformations needed to draw the
  267.        'famous' Sierpinski Triangle */
  268.     
  269.     /*copy_mtx(mul_mtx(scale_mtx((double)(0.5), (double)(0.5)),
  270.                        mul_mtx(xlate_mtx((double)(0.5) * (double)PLANE_ROWS, (double)0),
  271.                                id_mtx(3)                      
  272.                               )
  273.                       ), 
  274.                &aff_mtx[0]);
  275.     
  276.     copy_mtx(mul_mtx(scale_mtx((double)(0.5), (double)(0.5)),
  277.                      mul_mtx(xlate_mtx((double)0, (double)(0.5) * (double)PLANE_ROWS),
  278.                              id_mtx(3)                      
  279.                             )
  280.                      ), 
  281.              &aff_mtx[1]);
  282.     
  283.     copy_mtx(mul_mtx(scale_mtx((double)(0.5), (double)(0.5)),
  284.                      mul_mtx(xlate_mtx((double)0, (double)0),
  285.                              id_mtx(3)                      
  286.                             )
  287.                     ), 
  288.              &aff_mtx[2]);*/
  289.     
  290.     
  291.     /* below are the affine transformations for the NICK fractal */
  292.     
  293.     copy_mtx(mul_mtx(rot_mtx((double)90.0),
  294.                      mul_mtx(xlate_mtx((double)PLANE_ROWS, (double)0),
  295.                              mul_mtx(scale_mtx((double)(0.3273), (double)(0.3119)),
  296.                                      id_mtx(3)                      
  297.                                     )
  298.                             )
  299.                     ), 
  300.              &aff_mtx[0]);
  301.  
  302.     copy_mtx(mul_mtx(rot_mtx((double)90.0),
  303.                      mul_mtx(scale_mtx((double)(0.1455), (double)(0.2041)),
  304.                              mul_mtx(shear_mtx((double)0, (double)(-2.3750)),
  305.                                      mul_mtx(xlate_mtx((double)(0.4727) * (double)PLANE_ROWS, (double)0),
  306.                                              id_mtx(3)
  307.                                             )
  308.                                     )
  309.                             )
  310.                     ),
  311.         &aff_mtx[1]);
  312.           
  313.     copy_mtx(mul_mtx(rot_mtx((double)90.0),
  314.                      mul_mtx(scale_mtx((double)(0.3273), (double)(0.3119)),
  315.                              mul_mtx(xlate_mtx((double)(0.8000) * (double)PLANE_ROWS, (double)0),
  316.                                      id_mtx(3)
  317.                                     )
  318.                             )
  319.                     ), 
  320.              &aff_mtx[2]);
  321.     
  322.     copy_mtx(mul_mtx(scale_mtx((double)(0.1021), (double)(0.2727)),
  323.                      mul_mtx(xlate_mtx((double)(0.9455) * (double)PLANE_ROWS, (double)(0.7273) * (double)PLANE_ROWS),
  324.                             id_mtx(3)                      
  325.                            )
  326.                     ), 
  327.              &aff_mtx[3]);
  328.  
  329.     copy_mtx(mul_mtx(rot_mtx((double)90.0),
  330.                      mul_mtx(scale_mtx((double)(0.3273), (double)(0.2041)),
  331.                              mul_mtx(xlate_mtx((double)(1.2727) * (double)PLANE_ROWS, (double)0),
  332.                                      id_mtx(3)                      
  333.                                     )
  334.                             )
  335.                     ),
  336.         &aff_mtx[4]);
  337.           
  338.     copy_mtx(mul_mtx(rot_mtx((double)90.0),
  339.                      mul_mtx(scale_mtx((double)(0.3273), (double)(0.3119)),
  340.                              mul_mtx(xlate_mtx((double)(1.7455) * (double)PLANE_ROWS, (double)0),
  341.                                      id_mtx(3)
  342.                                     ) 
  343.                             )
  344.                     ), 
  345.              &aff_mtx[5]);
  346.  
  347.     copy_mtx(mul_mtx(rot_mtx((double)90.0),
  348.                      mul_mtx(scale_mtx((double)(0.1455), (double)(0.0851)),
  349.                              mul_mtx(xlate_mtx((double)(1.8909) * (double)PLANE_ROWS, (double)(0.7273) * (double)PLANE_ROWS),
  350.                                      id_mtx(3)
  351.                                     )
  352.                             )
  353.                     ), 
  354.              &aff_mtx[6]);
  355.  
  356.     copy_mtx(mul_mtx(rot_mtx((double)90.0),
  357.                      mul_mtx(scale_mtx((double)(0.1455), (double)(0.0851)),
  358.                              mul_mtx(xlate_mtx((double)(1.8909) * (double)PLANE_ROWS, (double)0),
  359.                                      id_mtx(3)                      
  360.                                     )
  361.                             )
  362.                     ),
  363.         &aff_mtx[7]);
  364.           
  365.     copy_mtx(mul_mtx(rot_mtx((double)90.0),
  366.                      mul_mtx(scale_mtx((double)(0.3273), (double)(0.1078)),
  367.                              mul_mtx(xlate_mtx((double)(2.2182) * (double)PLANE_ROWS, (double)(0.6545) * (double)PLANE_ROWS),
  368.                                      id_mtx(3)
  369.                                     )                      
  370.                             )
  371.                     ), 
  372.              &aff_mtx[8]);
  373.     
  374.     copy_mtx(mul_mtx(rot_mtx((double)90.0),
  375.                      mul_mtx(scale_mtx((double)(0.3273), (double)(0.1078)),
  376.                              mul_mtx(xlate_mtx((double)(2.2182) * (double)PLANE_ROWS, (double)0),
  377.                                      id_mtx(3)
  378.                                     )                      
  379.                             )
  380.                     ), 
  381.              &aff_mtx[9]);
  382.  
  383.     copy_mtx(mul_mtx(rot_mtx((double)90.0),
  384.                      mul_mtx(scale_mtx((double)(0.3273), (double)(0.3119)),
  385.                              mul_mtx(xlate_mtx((double)(2.6909) * (double)PLANE_ROWS, (double)0),
  386.                                      id_mtx(3)
  387.                                     ) 
  388.                             )
  389.                     ), 
  390.              &aff_mtx[10]);       
  391.     
  392.     
  393.     copy_mtx(mul_mtx(rot_mtx((double)-90.0),
  394.                      mul_mtx(scale_mtx((double)(0.3273), (double)(0.1078)),
  395.                              mul_mtx(shear_mtx((double)(0.4210), (double)0),
  396.                                      mul_mtx(xlate_mtx((double)(2.8363) * (double)PLANE_ROWS, (double)PLANE_ROWS),
  397.                                              id_mtx(3)
  398.                                             )
  399.                                     ) 
  400.                             )
  401.                     ), 
  402.              &aff_mtx[11]);
  403.  
  404.     copy_mtx(mul_mtx(rot_mtx((double)90.0),
  405.                      mul_mtx(scale_mtx((double)(0.3273), (double)(0.2041)),
  406.                              mul_mtx(shear_mtx((double)(-0.2222), (double)0),
  407.                                      mul_mtx(xlate_mtx((double)(3.1636) * (double)PLANE_ROWS, (double)0),
  408.                                              id_mtx(3)
  409.                                             )
  410.                                     ) 
  411.                             )
  412.                     ), 
  413.              &aff_mtx[12]);
  414.  
  415.     
  416.     OpenAll(); /* open graphics screen etc */
  417.     
  418.     /* draw the original shape - a rectangle around the border of the
  419.        transformed region */
  420.     SetAPen(rp, WHITE);
  421.     Move(rp, 0  + XOFF, 0  + YOFF);
  422.     Draw(rp, PLANE_COLS + XOFF - 1, 0  + YOFF);
  423.     Draw(rp, PLANE_COLS + XOFF - 1, PLANE_ROWS + YOFF - 1);
  424.     Draw(rp, 0  + XOFF, PLANE_ROWS + YOFF - 1);
  425.     Draw(rp, 0  + XOFF, 0  + YOFF);
  426.     
  427.     /* load the original shape into a 'bit-plane' */
  428.     load_plane_matrix(rp, &t);
  429.  
  430.     for (h = 1; h <= 8; h++) { /* transform shape 8 times */
  431.         for (i = 1; i <= PLANE_ROWS; i++) /* top to bottom */
  432.             for (j = 1; j <= PLANE_COLS; j++) { /* left to right */
  433.            
  434.                 if (window->UserPort->mp_SigBit) { /* pressed the CLOSEWINDOW button? */
  435.                      msg = (struct IntuiMessage *)GetMsg(window->UserPort);
  436.                           if (msg->Class == CLOSEWINDOW)
  437.                                clean_exit(RETURN_OK);
  438.                 }
  439.                 plot(window, (USHORT)((j - 1) + XOFF), (USHORT)(YOFF + PLANE_ROWS - i), WHITE);
  440.                 if (valu_bit_plane(&t, i, j))
  441.                    /* if there is something to transform do it with all
  442.                       NO_TRANSFORMS transformations */
  443.                    for (k = 0; k < NO_TRANSFORMS; k++) {
  444.                        assn_mtx(&u, 1, 1, (MATRIXTYPE)j);
  445.                        assn_mtx(&u, 1, 2, (MATRIXTYPE)i);
  446.                        v = mul_mtx(&u, &aff_mtx[k]);
  447.                        x = (int)valu_mtx(v, 1, 1);
  448.                        y = (int)valu_mtx(v, 1, 2);
  449.                        if ((x >= 1) && (x <= PLANE_COLS) &&
  450.                            (y >= 1) && (y <= PLANE_ROWS))
  451.                               assn_bit_plane(&s, (unsigned int)(y), (unsigned int)(x), TRUE);
  452.                    }
  453.                 
  454.             }
  455.             copy_bit_plane(&s, &t);
  456.             /* make new shape the old shape for next time around */
  457.             clr_bit_plane(&s); /* clear the new shape */
  458.             clr_screen(); /* clear screen */
  459.        
  460.             /* show the results of last transformations */
  461.             for (i = 1; i <= PLANE_ROWS; i++)
  462.                  for (j = 1; j <= PLANE_COLS; j++)
  463.                       if (valu_bit_plane(&t, i, j))
  464.                            plot(window, (USHORT)((j - 1) + XOFF), (USHORT)(YOFF + PLANE_ROWS - i), WHITE);
  465.                 
  466.     }
  467.     
  468.     /* all transformations are done, so wait forever for the user to close
  469.        the window */
  470.     while (TRUE) {
  471.        Wait(1 << window->UserPort->mp_SigBit);
  472.        msg = (struct IntuiMessage *)GetMsg(window->UserPort);
  473.           if (msg->Class == CLOSEWINDOW)
  474.                   clean_exit(RETURN_OK);
  475.    }
  476.    
  477. }
  478.  
  479. BOOL init_mtx(struct matrix *mtx, unsigned int r, unsigned int c)
  480. /* set up a matrix of given dimensions */ 
  481. {
  482.     unsigned int size;
  483.  
  484.     if ((r >= 1) && (c >= 1)) {
  485.        mtx->rows = r;
  486.        mtx->cols = c;
  487.        size = r * c;
  488.        mtx->table = calloc(size, sizeof(MATRIXTYPE));
  489.        return (TRUE);
  490.     }
  491.     else
  492.        return (FALSE);
  493. }
  494.  
  495. BOOL init_bit_plane(struct bit_plane *mtx, unsigned int r, unsigned int c)
  496. /* set up a bit plane of given dimensions */
  497. {
  498.     unsigned int size;
  499.  
  500.     if ((r >= 1) && (c >= 1)) {
  501.        mtx->rows = r;
  502.        mtx->cols = c;
  503.        size = r * ((c >> 3) + 1);
  504.        mtx->table = calloc(size, sizeof(UBYTE));
  505.        if (mtx->table)
  506.           return (TRUE);
  507.        else
  508.           return (FALSE);
  509.     }
  510.     else
  511.        return (FALSE);
  512. }
  513.  
  514. BOOL copy_bit_plane(struct bit_plane *src, struct bit_plane *des)
  515. /* copy one bit plane to another */
  516. {
  517.     UBYTE *j;
  518.     unsigned int i, size;
  519.  
  520.     if ((src->rows == des->rows) && (src->cols == des->cols) &&
  521.         (src->rows >= 1) && (src->cols >= 1) &&
  522.         (src->table) && (des->table)) {
  523.              size = src->rows * ((src->cols >> 3) + 1);
  524.              j = src->table;
  525.              for (i = 0; i < size; i++, j++)
  526.                  *(des->table + i) = *j;
  527.              return (TRUE);
  528.     }
  529.     else
  530.         return (FALSE);
  531. }
  532.  
  533. BOOL clr_bit_plane(struct bit_plane *mtx)
  534. /* assign all FALSE values to each element of a bit plane */
  535. {
  536.     unsigned int i, size;
  537.  
  538.     if ((mtx->rows >= 1) && (mtx->cols >= 1) &&
  539.         (mtx->table)) {
  540.         size = mtx->rows * ((mtx->cols >> 3) + 1);
  541.         for (i = 0; i < size; i++)
  542.             *(mtx->table + i) = 0;
  543.         return (TRUE);
  544.     }
  545.     else
  546.         return (FALSE);
  547. }
  548.  
  549. VOID kill_mtx(struct matrix *mtx)
  550. /* redeem memory allocated to a matrix */
  551. {
  552.     if (mtx->table)
  553.        free(mtx->table);
  554.     mtx->table = NULL;
  555.     mtx->rows = 0;
  556.     mtx->cols = 0;
  557. }
  558.  
  559. VOID kill_bit_plane(struct bit_plane *mtx)
  560. /* redeem all memory allocated to a bit plane */
  561. {
  562.     if (mtx->table)
  563.        free(mtx->table);
  564.     mtx->table = NULL;
  565.     mtx->rows = 0;
  566.     mtx->cols = 0;
  567. }
  568.  
  569. BOOL copy_mtx(struct matrix *src, struct matrix *des)
  570. /* copy one matrix to another */
  571. {
  572.    MATRIXTYPE *j;
  573.    unsigned int i, size;
  574.    
  575.    if ((src->rows == des->rows) && (src->cols == des->cols)) {
  576.       
  577.       size = src->rows * src->cols;
  578.       j = src->table;
  579.       for (i = 0; i < size; i++, j++)
  580.          *(des->table + i) = *j;
  581.       
  582.       return TRUE;
  583.    }
  584.    else
  585.       return FALSE;
  586. }
  587.  
  588.  
  589. BOOL within_mtx(struct matrix *mtx, unsigned int r, unsigned int c)
  590. /* return whether or not the element described is in a the matrix given */
  591. {
  592.     if ((r >= 1) && (c >= 1) && (r <= mtx->rows) && (c <= mtx->cols))
  593.        return (TRUE);
  594.     else
  595.        return (FALSE);
  596. }
  597.  
  598. BOOL within_bit_plane(struct bit_plane *mtx, unsigned int r, unsigned int c)
  599. /* return whether or not the element described is in a the bit plane given */
  600. {
  601.     if ((r >= 1) && (c >= 1) && (r <= mtx->rows) && (c <= mtx->cols))
  602.        return (TRUE);
  603.     else
  604.        return (FALSE);
  605. }
  606.  
  607. BOOL assn_mtx(struct matrix *mtx, unsigned int r, unsigned int c, MATRIXTYPE data)
  608. /* assign a value to a matrix */
  609. {
  610.     if (within_mtx(mtx, r, c)) {
  611.        *(mtx->table + mtx->cols * (r - 1) + (c - 1)) = data;
  612.        return (TRUE);
  613.     }
  614.     else
  615.        return (FALSE);
  616. }
  617.  
  618. BOOL assn_bit_plane(struct bit_plane *mtx, unsigned int r, unsigned int c, BOOL value)
  619. /* assign a logical value to a bit plane */
  620. {
  621.     UBYTE *location;
  622.  
  623.     if (within_bit_plane(mtx, r, c)) {
  624.        location = mtx->table +
  625.                   (r - 1) * ((mtx->cols >> 3) + 1) + ((c - 1) >> 3);
  626.        if (value)
  627.           *location |= 1 << (0x0007 & (c - 1));
  628.        else
  629.           *location &= ~(1 << (0x0007 & (c - 1)));
  630.        return (TRUE);
  631.     }
  632.     else
  633.        return (FALSE);
  634. }
  635.  
  636. BOOL valu_bit_plane(struct bit_plane *mtx, unsigned int r, unsigned int c)
  637. /* return the element asked for of the matrix given */
  638. {
  639.     UBYTE *location;
  640.  
  641.     location = mtx->table +
  642.                (r - 1) * ((mtx->cols >> 3) + 1) + ((c - 1) >> 3);
  643.     return (BOOL)(*location & (1 << (0x0007 & (c - 1))) );
  644. }
  645.  
  646. VOID prin_bit_plane(struct bit_plane *mtx)
  647. /* display the contents of a bit plane */
  648. {
  649.     unsigned int i, j;
  650.  
  651.     for (i = 1; i <= mtx->rows; i++) {
  652.         for (j = 1; j <= mtx->cols; j++)
  653.             printf("%s", ((valu_bit_plane(mtx, i, j)) ? ("##") : ("  ")));
  654.         printf("\n");
  655.     }
  656.     printf("\n");
  657. }
  658.  
  659. struct matrix *mul_mtx(struct matrix *mtx1, struct matrix *mtx2)
  660. /* FUNCTIONALLY return the product of two matrices (not a procedure!) */
  661. {
  662.     unsigned int i, j, k;
  663.     MATRIXTYPE   op_1, op_2, sum;
  664.     struct matrix *prod, *temp_store;
  665.  
  666.     if (mtx1->cols == mtx2->rows) {
  667.        if (prod_1.table) {
  668.           temp_store = &prod_1;
  669.           prod = &prod_2;
  670.        }
  671.        else {
  672.           temp_store = &prod_2;
  673.           prod = &prod_1;
  674.        }
  675.  
  676.        init_mtx(prod, mtx1->rows, mtx2->cols);
  677.  
  678.        for (k = 0; k < mtx1->rows; k++) {
  679.            for (j = 0; j < mtx2->cols; j++) {
  680.                sum = 0;
  681.                for (i = 0; i < mtx1->cols; i++) {
  682.                    op_1 = *(mtx2->table + mtx2->cols * i + j);
  683.                    op_2 = *(mtx1->table + mtx1->cols * k + i);
  684.  
  685.                    if (op_2 != 0)
  686.                       if (op_2 == XONE)
  687.                          sum += op_1;
  688.                       else
  689.                          sum += xmul(op_1, op_2);
  690.                }
  691.                *(prod->table + mtx2->cols * k + j) = sum;
  692.            }
  693.        }
  694.        if (temp_store->table)
  695.            kill_mtx(temp_store);
  696.        return (prod);
  697.     }
  698.     else
  699.        return ((struct matrix *)(NULL));
  700. }
  701.  
  702. VOID fill_mtx(struct matrix *mtx, MATRIXTYPE data[])
  703. /* a convenience procedure to fill a matrix with the conents of an array */
  704. {
  705.     unsigned int i, size;
  706.  
  707.     size = mtx->rows * mtx->cols;
  708.     for (i = 0; i < size; i++)
  709.         *(mtx->table + i) = data[i];
  710. }
  711.  
  712. MATRIXTYPE valu_mtx(struct matrix *mtx, unsigned int r, unsigned int c)
  713. /* return the value of a matrix */
  714. {
  715.     if (within_mtx(mtx, r, c))
  716.        return *(mtx->table + mtx->cols * (r - 1) + (c - 1));
  717.     else
  718.        return (FALSE);
  719. }
  720.  
  721. VOID prin_mtx(struct matrix *mtx)
  722. /* display the contents of a matrix */
  723. {
  724.     unsigned int i, j;
  725.  
  726.     for (j = 1; j <= mtx->rows; j++) {
  727.         for (i = 1; i <= mtx->cols; i++)
  728.             printf("%2.4lf ", xtof(valu_mtx(mtx, j, i)));
  729.         printf("\n");
  730.     }
  731.     printf("\n");
  732. }
  733.  
  734.  
  735. struct matrix *id_mtx(unsigned int size)
  736. /* return the identity matrix of the size specified:
  737.  
  738.  
  739.            1 0 0 0
  740.            0 1 0 0   (This is the identity matrix of size 4)
  741.            0 0 1 0 
  742.            0 0 0 1
  743. */
  744. {
  745.     unsigned int i;
  746.  
  747.     if (size >= 1) {
  748.        kill_mtx(&id);
  749.        init_mtx(&id, size, size);
  750.        for (i = 1; i <= size; i++)
  751.            assn_mtx(&id, i, i, XONE);
  752.        return (&id);
  753.     }
  754.     else
  755.        return ((struct matrix *)(NULL));
  756. }
  757.  
  758. struct matrix *shear_mtx(double shear_x, double shear_y)
  759. /* return the matrix used to shear point vectors */
  760. {
  761.    
  762.    if (!shr.table) {
  763.       init_mtx(&shr, 3, 3);
  764.       copy_mtx(id_mtx(3), &shr);
  765.    }
  766.    assn_mtx(&shr, 2, 1, (MATRIXTYPE)shear_x);
  767.    assn_mtx(&shr, 1, 2, (MATRIXTYPE)shear_y);
  768.    
  769.    return (&shr);
  770. }
  771.  
  772. struct matrix *scale_mtx(double scale_x, double scale_y)
  773. /* return the matrix used to scale vectors */
  774. {
  775.    
  776.    if (!scl.table) {
  777.       init_mtx(&scl, 3, 3);
  778.       copy_mtx(id_mtx(3), &scl);
  779.    }
  780.    assn_mtx(&scl, 1, 1, (MATRIXTYPE)scale_x);
  781.    assn_mtx(&scl, 2, 2, (MATRIXTYPE)scale_y);
  782.    
  783.    return (&scl);
  784. }
  785.  
  786. struct matrix *rot_mtx(double degs)
  787. /* return the matrix used to rotate vectors */
  788. {
  789.    
  790.    if (!rot.table) {
  791.       init_mtx(&rot, 3, 3);
  792.       copy_mtx(id_mtx(3), &rot);
  793.    }
  794.    assn_mtx(&rot, 1, 1, (MATRIXTYPE)( xcos(dtor(degs))));
  795.    assn_mtx(&rot, 1, 2, (MATRIXTYPE)( xsin(dtor(degs))));
  796.    assn_mtx(&rot, 2, 1, (MATRIXTYPE)(-xsin(dtor(degs))));
  797.    assn_mtx(&rot, 2, 2, (MATRIXTYPE)( xcos(dtor(degs))));
  798.    
  799.    return (&rot);
  800. }
  801.    
  802. struct matrix *xlate_mtx(double d_x, double d_y)
  803. /* return the matrix used to translate vectors */
  804. {
  805.    
  806.    if (!xlt.table) {
  807.       init_mtx(&xlt, 3, 3);
  808.       copy_mtx(id_mtx(3), &xlt);
  809.    }
  810.    assn_mtx(&xlt, 3, 1, (MATRIXTYPE)d_x);
  811.    assn_mtx(&xlt, 3, 2, (MATRIXTYPE)d_y);
  812.    
  813.    return (&xlt);
  814. }
  815.    
  816. VOID clr_screen(VOID)
  817. {
  818.    SetAPen(rp, BLACK);
  819.    RectFill(rp, 0, 10, screen->Width - 1, screen->Height - 1);
  820.  
  821. }
  822.  
  823. VOID load_plane_matrix(struct RastPort *rp, struct bit_plane *t)
  824. {
  825.    
  826.    unsigned int i, j;
  827.    
  828.    for (i = 1; i <= PLANE_ROWS; i++) {
  829.         if (window->UserPort->mp_SigBit) { /* pressed the CLOSEWINDOW button? */
  830.                      msg = (struct IntuiMessage *)GetMsg(window->UserPort);
  831.                           if (msg->Class == CLOSEWINDOW)
  832.                                clean_exit(RETURN_OK);
  833.                 }
  834.         for (j = 1; j <= PLANE_COLS; j++)
  835.                 assn_bit_plane(t, i, j, (BOOL)(ReadPixel(rp, (j - 1 + XOFF), (YOFF + PLANE_ROWS - i))));
  836.    }
  837. }
  838.  
  839. VOID OpenAll(VOID)
  840. {
  841.    
  842.    printf("* NICK Fractal *\n");
  843.    printf("by Dave Lyneham, 1991.\n");
  844.    printf("This program draws a fractal\n");
  845.    printf("word (NICK) but it takes\n");
  846.    printf("a long time. (~2 hours)\n\n");
  847.    printf("CLICK THE CLOSEWINDOW GADGET\nTO ABORT THE PROGRAM");
  848.    
  849.    IntuitionBase = (struct IntuitionBase *)
  850.       OpenLibrary("intuition.library", LIB_REV);
  851.    
  852.    if (IntuitionBase == NULL)
  853.       clean_exit(RETURN_WARN);
  854.       
  855.    GfxBase =  (struct GfxBase *)
  856.    OpenLibrary("graphics.library", LIB_REV);
  857.    if (GfxBase == NULL)
  858.       clean_exit(RETURN_WARN);
  859.    
  860.    
  861.    openViewing();
  862.  
  863. }
  864.  
  865. VOID plot(struct Window *Window, USHORT x, USHORT y, USHORT pen)
  866. {
  867.    if ((x <= Window->Width) && (y <= Window->Height) && (x >= 0) && (y >= BORDERTHICK)) {
  868.       SetAPen(Window->RPort, pen);
  869.       WritePixel(Window->RPort, x, y);
  870.    }
  871. }
  872.  
  873. VOID openViewing(VOID)
  874. {
  875.    struct NewScreen NewScreen = {
  876.       
  877.       0, 0,
  878.       0, 0,
  879.       1,
  880.       1, 0,
  881.       NULL,
  882.       CUSTOMSCREEN,
  883.       NULL,
  884.       NULL,
  885.       NULL,
  886.       NULL,
  887.    };
  888.  
  889.  
  890.    struct NewWindow NewWindow = {
  891.    
  892.       0, 1,
  893.       0, 0,
  894.       1, 0,
  895.       CLOSEWINDOW,
  896.       WINDOWCLOSE |  ACTIVATE,
  897.       NULL,
  898.       NULL,
  899.       NULL,
  900.       NULL,
  901.       NULL,
  902.       0, 0,
  903.       -1, -1,
  904.       CUSTOMSCREEN
  905.    };
  906.    
  907.    NewScreen.Width      = _HIRES_WIDTH;
  908.    NewScreen.Height     = _HIRES_HEIGHT;
  909.    NewScreen.ViewModes  = LACE | HIRES; 
  910.    
  911.    screen = (struct Screen *)OpenScreen(&NewScreen);
  912.    if (screen == NULL)
  913.       clean_exit(RETURN_WARN);
  914.       
  915.    NewWindow.Screen = screen;
  916.    NewWindow.Width  = screen->Width;
  917.    NewWindow.Height = screen->Height - 1;
  918.          
  919.    window = (struct Window *)OpenWindow(&NewWindow);
  920.    if (window == NULL)
  921.       clean_exit(RETURN_WARN);
  922.    
  923.    rp = window->RPort;
  924.    vp = (struct ViewPort *)ViewPortAddress(window);
  925.    SetDrMd(rp, JAM2);
  926.    setColours();
  927.    
  928. }
  929.  
  930. VOID closeViewing()
  931. {
  932.    if (window)
  933.       CloseWindow(window);
  934.  
  935.    if (screen)
  936.       CloseScreen(screen);
  937. }
  938.  
  939. VOID clean_exit(int returnValue)
  940. {
  941.    
  942.    unsigned int i;
  943.    
  944.    kill_bit_plane(&s);
  945.    kill_bit_plane(&t);
  946.    for (i = 0; i < NO_TRANSFORMS; i++)
  947.         kill_mtx(&aff_mtx[i]);
  948.    kill_mtx(&u);
  949.    kill_mtx(&prod_1);
  950.    kill_mtx(&prod_2);
  951.    kill_mtx(&id);
  952.    kill_mtx(&scl);
  953.    kill_mtx(&shr);
  954.    kill_mtx(&xlt);
  955.    kill_mtx(&rot); 
  956.    
  957.    closeViewing();
  958.       
  959.    if (GfxBase)
  960.       CloseLibrary((struct Library *)GfxBase);
  961.    
  962.    if (IntuitionBase)
  963.       CloseLibrary((struct Library *)IntuitionBase);
  964.    
  965.    if (returnValue != RETURN_OK)
  966.       DisplayBeep(NULL);
  967.    
  968.    exit(returnValue);
  969. }
  970.  
  971. VOID setColours(VOID)
  972. {   
  973.    SetRGB4(vp, BLACK, 0, 0, 0);
  974.    SetRGB4(vp, WHITE, 15, 15, 15);
  975.    
  976.    SetAPen(rp, BLACK);
  977.    RectFill(rp, 0, 10, screen->Width - 1, screen->Height - 1);
  978. }